/**
 * 格式化日期
 * @param {Date|String|Number} date 日期对象/日期字符串/时间戳
 * @param {String} format 格式化模式，默认 'YYYY-MM-DD HH:mm:ss'
 * @returns {String} 格式化后的日期字符串
 */
const formatDate = (date, format = 'YYYY-MM-DD HH:mm:ss') => {
  if (!date) return ''
  
  let dt = date
  if (typeof date === 'string') {
    dt = new Date(date.replace(/-/g, '/'))
  } else if (typeof date === 'number') {
    dt = new Date(date)
  }
  
  const year = dt.getFullYear()
  const month = dt.getMonth() + 1
  const day = dt.getDate()
  const hour = dt.getHours()
  const minute = dt.getMinutes()
  const second = dt.getSeconds()
  
  return format
    .replace(/YYYY/g, year)
    .replace(/MM/g, month < 10 ? '0' + month : month)
    .replace(/DD/g, day < 10 ? '0' + day : day)
    .replace(/HH/g, hour < 10 ? '0' + hour : hour)
    .replace(/mm/g, minute < 10 ? '0' + minute : minute)
    .replace(/ss/g, second < 10 ? '0' + second : second)
}

/**
 * 格式化金额
 * @param {Number} money 金额
 * @param {Number} decimals 小数位数，默认2位
 * @returns {String} 格式化后的金额字符串
 */
const formatMoney = (money, decimals = 2) => {
  if (isNaN(money)) return '0.00'
  
  const num = parseFloat(money)
  return num.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

/**
 * 获取文件扩展名
 * @param {String} filename 文件名
 * @returns {String} 文件扩展名
 */
const getFileExt = (filename) => {
  if (!filename) return ''
  return filename.substring(filename.lastIndexOf('.') + 1).toLowerCase()
}

/**
 * 检查文件类型是否合法
 * @param {String} filename 文件名
 * @param {Array} allowTypes 允许的文件类型数组
 * @returns {Boolean} 是否合法
 */
const checkFileType = (filename, allowTypes = ['jpg', 'jpeg', 'png', 'pdf']) => {
  const ext = getFileExt(filename)
  return allowTypes.includes(ext)
}

/**
 * 获取随机字符串
 * @param {Number} length 字符串长度，默认16
 * @returns {String} 随机字符串
 */
const randomString = (length = 16) => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  
  return result
}

/**
 * 显示消息提示框
 * @param {String} title 提示的内容
 * @param {String} icon 图标，success/error/loading/none
 * @param {Number} duration 提示的延迟时间，默认1.5秒
 */
const showToast = (title, icon = 'none', duration = 1500) => {
  wx.showToast({
    title,
    icon,
    duration
  })
}

/**
 * 显示模态对话框
 * @param {String} title 提示的标题
 * @param {String} content 提示的内容
 * @param {Boolean} showCancel 是否显示取消按钮，默认true
 * @returns {Promise} Promise对象
 */
const showModal = (title, content, showCancel = true) => {
  return new Promise((resolve, reject) => {
    wx.showModal({
      title,
      content,
      showCancel,
      success(res) {
        if (res.confirm) {
          resolve(true)
        } else if (res.cancel) {
          resolve(false)
        }
      },
      fail() {
        reject(new Error('模态框显示失败'))
      }
    })
  })
}

/**
 * 显示loading提示框
 * @param {String} title 提示的内容
 * @param {Boolean} mask 是否显示透明蒙层，防止触摸穿透，默认true
 */
const showLoading = (title = '加载中', mask = true) => {
  wx.showLoading({
    title,
    mask
  })
}

/**
 * 隐藏loading提示框
 */
const hideLoading = () => {
  wx.hideLoading()
}

/**
 * 发起网络请求
 * @param {String} url 请求地址
 * @param {Object} data 请求参数
 * @param {String} method 请求方法
 * @param {Boolean} loading 是否显示loading，默认true
 * @returns {Promise} Promise对象
 */
const request = (url, data = {}, method = 'GET', loading = true) => {
  const app = getApp()
  const baseUrl = app.globalData.baseUrl
  const token = app.globalData.token || wx.getStorageSync('token')
  
  if (loading) {
    showLoading()
  }
  
  return new Promise((resolve, reject) => {
    wx.request({
      url: /^(http|https):\/\//.test(url) ? url : baseUrl + url,
      data,
      method,
      header: {
        'content-type': 'application/json',
        'Authorization': token ? `Bearer ${token}` : ''
      },
      success(res) {
        if (loading) {
          hideLoading()
        }
        
        if (res.statusCode === 200) {
          if (res.data.code === 200) {
            resolve(res.data)
          } else if (res.data.code === 401) {
            // 未登录或token过期
            wx.removeStorageSync('token')
            wx.removeStorageSync('userInfo')
            app.globalData.token = ''
            app.globalData.userInfo = null
            
            wx.navigateTo({
              url: '/pages/login/index'
            })
            
            reject(new Error(res.data.message || '请先登录'))
          } else {
            showToast(res.data.message || '请求失败')
            reject(new Error(res.data.message || '请求失败'))
          }
        } else {
          showToast(`网络错误(${res.statusCode})`)
          reject(new Error(`网络错误(${res.statusCode})`))
        }
      },
      fail(err) {
        if (loading) {
          hideLoading()
        }
        
        showToast('网络请求失败')
        reject(new Error('网络请求失败'))
      }
    })
  })
}

module.exports = {
  formatDate,
  formatMoney,
  getFileExt,
  checkFileType,
  randomString,
  showToast,
  showModal,
  showLoading,
  hideLoading,
  request
} 